<?php
$nosession = true;
$nosecu = true;
include("./includes/common.php");

// Basic response headers
@header('X-Content-Type-Options: nosniff');
@header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
@header('Pragma: no-cache');
// CORS (for JSON API usage)
if(isset($_SERVER['HTTP_ORIGIN'])){
	@header('Access-Control-Allow-Origin: *');
	@header('Access-Control-Allow-Methods: POST');
	@header('Access-Control-Allow-Headers: Content-Type, X-API-Key');
}

if(!$conf['api_open']) json_format(['code'=>-4, 'msg'=>'当前站点未开启上传API']);

// 请求方法校验
if($_SERVER['REQUEST_METHOD']!=='POST'){
	json_format(['code'=>-4, 'msg'=>'请求方法不允许']);
}

// 允许来源校验（可选）
if(!empty($conf['api_referer'])){
	$referers = explode('|',$conf['api_referer']);
	$ref = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
	$url_arr = $ref ? parse_url($ref) : null;
	$host = ($url_arr && isset($url_arr['host'])) ? $url_arr['host'] : '';
	if(empty($host) || !in_array($host, $referers)){
		json_format(['code'=>-4, 'msg'=>'来源地址不正确']);
	}
}

// 读取 apikey（Header 优先，其次 POST 字段）
$headers = function_exists('getallheaders') ? getallheaders() : [];
$apiKey = null;
if(isset($headers['X-API-Key'])) $apiKey = trim($headers['X-API-Key']);
elseif(isset($_SERVER['HTTP_X_API_KEY'])) $apiKey = trim($_SERVER['HTTP_X_API_KEY']);
elseif(isset($_POST['apikey'])) $apiKey = trim($_POST['apikey']);

if(empty($apiKey)){
	json_format(['code'=>-3, 'msg'=>'缺少 apikey 参数']);
}

// 确认表结构支持 api_key 字段
$hasApiKeyCol = $DB->getRow("SHOW COLUMNS FROM pre_user LIKE 'api_key'");
if(!$hasApiKeyCol){
	json_format(['code'=>-5, 'msg'=>'未检测到用户表 api_key 字段，请先在 pre_user 表添加 api_key(varchar(64)) 并为用户生成密钥']);
}

// 根据 apikey 确认用户与权限（启用状态）
$user = $DB->getRow("SELECT uid, enable, group_id FROM pre_user WHERE api_key=:ak LIMIT 1", [':ak'=>$apiKey]);
if(!$user){
	json_format(['code'=>-2, 'msg'=>'apikey 无效或用户不存在']);
}
if(intval($user['enable']) !== 1){
	json_format(['code'=>-2, 'msg'=>'当前用户已被禁用']);
}
$uid = intval($user['uid']);

// 根据用户组选择云存储类型（未配置则回退到站点默认）
$storageType = get_user_storage_type($uid, $DB, $conf['storage']);
$stor = \lib\StorHelper::getModel($storageType);

if(!isset($_FILES['file'])) json_format(['code'=>-1, 'msg'=>'请选择文件']);
$name = trim(htmlspecialchars($_FILES['file']['name']));
$size = intval($_FILES['file']['size']);
if($conf['upload_size']>0 && $size > $conf['upload_size']*1024*1024){
	showresult(['code'=>-1, 'msg'=>'文件大小超过限制（最大 '.$conf['upload_size'].'MB）']);
}
$hide = isset($_POST['show']) && $_POST['show']==1 ? 0 : 1;
$ispwd = intval($_POST['ispwd'] ?? 0);
$pwd = $ispwd==1 ? trim(htmlspecialchars($_POST['pwd'] ?? '')) : null;
$name = str_replace(['/','\\',':','*','"','<','>','|','?'],'',$name);
if(empty($name)) json_format(['code'=>-1, 'msg'=>'文件名不能为空']);
if($ispwd==1 && !empty($pwd)){
	if (!preg_match('/^[a-zA-Z0-9]+$/', $pwd)) {
		json_format(['code'=>-1, 'msg'=>'文件密码只能为字母和数字']);
	}
}
$ext = get_file_ext($name);
if($conf['type_block']){
	$type_block = explode('|',$conf['type_block']);
	if(in_array($ext,$type_block)){
		json_format(['code'=>-1, 'msg'=>'文件上传失败', 'error'=>'block']);
	}
}
if($conf['name_block']){
	$name_block = explode('|',$conf['name_block']);
	foreach($name_block as $row){
		if($row !== '' && strpos($name,$row)!==false){
			json_format(['code'=>-1, 'msg'=>'文件上传失败', 'error'=>'block']);
		}
	}
}

$hash = md5_file($_FILES['file']['tmp_name']);
$row = $DB->getRow("SELECT * FROM pre_file WHERE hash=:hash", [':hash'=>$hash]);
if($row){
	unset($_SESSION['csrf_token']);
	$downurl = $siteurl.'user/down.php/'.$row['hash'].'.'.$row['type'];
	if(!empty($row['pwd'])) $downurl .= '&'.$row['pwd'];
	$result = [
		'code'=>0,
		'msg'=>'本站已存在该文件',
		'exists'=>1,
		'hash'=>$hash,
		'name'=>$name,
		'size'=>$size,
		'type'=>$ext,
		'id'=>$row['id'],
		'downurl'=>$downurl
	];
	if(is_view($row['type'])) $result['viewurl'] = $siteurl.'view.php/'.$hash.'.'.$row['type'];
	json_format($result);
}

// 上传到对应云存储
$result = $stor->upload($hash, $_FILES['file']['tmp_name'], minetype($ext));
if(!$result) json_format(['code'=>-1, 'msg'=>'文件上传失败', 'error'=>'stor']);

// 写入数据库（带 uid 与存储类型）
$sds = $DB->exec(
	"INSERT INTO `pre_file` (`name`,`type`,`size`,`hash`,`addtime`,`ip`,`hide`,`pwd`,`uid`,`storage`) values (:name,:type,:size,:hash,NOW(),:ip,:hide,:pwd,:uid,:storage)",
	[
		':name'=>$name,
		':type'=>$ext,
		':size'=>$size,
		':hash'=>$hash,
		':ip'=>$clientip,
		':hide'=>$hide,
		':pwd'=>$pwd,
		':uid'=>$uid,
		':storage'=>$storageType
	]
);
if(!$sds) json_format(['code'=>-1, 'msg'=>'上传失败'.$DB->error(), 'error'=>'database']);
$id = $DB->lastInsertId();

$type_image = explode('|',$conf['type_image']);
$type_video = explode('|',$conf['type_video']);
if($conf['green_check']>0 && in_array($ext,$type_image)){
	if(checkImage($hash, $ext)){
		$DB->exec("UPDATE `pre_file` SET `block`=1 WHERE `id`='{$id}' LIMIT 1");
	}
}
if($conf['videoreview']==1 && in_array($ext,$type_video)){
	$DB->exec("UPDATE `pre_file` SET `block`=2 WHERE `id`='{$id}' LIMIT 1");
}

$downurl = $siteurl.'user/down.php/'.$hash.'.'.$ext;
if(!empty($pwd)) $downurl .= '&'.$pwd;
$out = [
	'code'=>0,
	'msg'=>'文件上传成功！',
	'exists'=>0,
	'hash'=>$hash,
	'name'=>$name,
	'size'=>$size,
	'type'=>$ext,
	'id'=>$id,
	'uid'=>$uid,
	'storage'=>$storageType,
	'downurl'=>$downurl
];
if(is_view($ext)) $out['viewurl'] = $siteurl.'user/view.php/'.$hash.'.'.$ext;
json_format($out);
